mod mysql;
mod sqlite;

use std::collections::HashMap;

use model_graph_types::{
    database::{DataSource, DatabaseType},
    datasource::{DeleteCondition, DeleteOptions, InsertOptions, UpdateCondition, UpdateOptions},
    modeling::{system_meta_database, Class, ClassPersistence, Value},
};

pub fn genertate_query_one_sql(
    meta_datasource: &Option<DataSource>,
    ds_id: u32,
    database_type: &DatabaseType,
    clazz: &Class,
    keys: &Vec<String>,
    mapping: ClassPersistence,
) -> anyhow::Result<String> {
    let meta_datasource = if let Some(meta) = meta_datasource {
        meta
    } else {
        &system_meta_database()?
    };
    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_query_one_sql(meta_datasource, clazz, keys, mapping);
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_query_one_sql(meta_datasource, clazz, keys, mapping);
        }
        _ => {}
    }
    Err(anyhow::anyhow!("没有找到对应的数据库类型"))
}

pub fn genertate_delete_by_keys_sql(
    meta_datasource: &Option<DataSource>,
    database_type: &DatabaseType,
    clazz: &Class,
    keys: &Vec<String>,
    mapping: ClassPersistence,
) -> anyhow::Result<String> {
    let meta_datasource = if let Some(meta) = meta_datasource {
        meta
    } else {
        &system_meta_database()?
    };
    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_delete_by_keys_sql(meta_datasource, clazz, keys, mapping);
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_delete_by_keys_sql(meta_datasource, clazz, keys, mapping);
        }
        _ => {}
    }
    Err(anyhow::anyhow!("没有找到对应的数据库类型"))
}

pub fn genertate_where_by_keys_sql(
    database_type: &DatabaseType,
    clazz: &Class,
    primary_key: &String,
    keys: &Vec<String>,
) -> anyhow::Result<String> {
    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_where_by_keys_sql(clazz, primary_key, keys);
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_where_by_keys_sql(clazz, primary_key, keys);
        }
        _ => {}
    }
    Err(anyhow::anyhow!("没有找到对应的数据库类型"))
}

pub fn genertate_update_by_keys_sql(
    meta_datasource: &Option<DataSource>,
    ds_id: u32,
    database_type: &DatabaseType,
    clazz: &Class,
    keys: &Vec<String>,
    primary_key: &String,
    value: HashMap<String, Value>,
    mapping: ClassPersistence,
) -> anyhow::Result<(String, Vec<Value>)> {
    let meta_datasource = if let Some(meta) = meta_datasource {
        meta
    } else {
        &system_meta_database()?
    };
    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_update_by_keys_sql(
                meta_datasource,
                clazz,
                keys,
                primary_key,
                value,
                mapping,
            );
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_update_by_keys_sql(
                meta_datasource,
                clazz,
                keys,
                primary_key,
                value,
                mapping,
            );
        }
        _ => {}
    }
    Err(anyhow::anyhow!("没有找到对应的数据库类型"))
}

pub async fn genertate_insert_data_sql(
    meta_datasource: &Option<DataSource>,
    database_type: &DatabaseType,
    class_identifier: &String,
    value: HashMap<String, Value>,
    options: Option<InsertOptions>,
) -> anyhow::Result<(String, Vec<Value>)> {
    let meta_datasource = if let Some(meta) = meta_datasource {
        meta
    } else {
        &system_meta_database()?
    };
    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_insert_data_sql(
                meta_datasource,
                class_identifier,
                value,
                options,
            )
            .await;
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_insert_data_sql(
                meta_datasource,
                class_identifier,
                value,
                options,
            )
            .await;
        }
        _ => {}
    }
    Ok((String::new(), vec![]))
}

pub async fn genertate_delete_data_sql(
    meta_datasource: &Option<DataSource>,
    ds_id: u32,
    database_type: &DatabaseType,
    class_identifier: &String,
    conditions: DeleteCondition,
    options: Option<DeleteOptions>,
) -> anyhow::Result<(String, Vec<Value>)> {
    let meta_datasource = if let Some(meta) = meta_datasource {
        meta
    } else {
        &system_meta_database()?
    };
    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_delete_data_sql(
                ds_id,
                meta_datasource,
                class_identifier,
                conditions,
                options,
            )
            .await;
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_delete_data_sql(
                ds_id,
                meta_datasource,
                class_identifier,
                conditions,
                options,
            )
            .await;
        }
        _ => {}
    }
    Ok((String::new(), vec![]))
}

pub async fn genertate_update_data_sql(
    meta_datasource: &Option<DataSource>,
    ds_id: u32,
    database_type: &DatabaseType,
    class_identifier: &String,
    conditions: UpdateCondition,
    values: HashMap<String, Value>,
    options: Option<UpdateOptions>,
) -> anyhow::Result<(String, Vec<Value>)> {
    let meta_datasource = if let Some(meta) = meta_datasource {
        meta
    } else {
        &system_meta_database()?
    };

    match database_type {
        DatabaseType::MySQL => {
            return mysql::genertate_update_data_sql(
                ds_id,
                meta_datasource,
                class_identifier,
                conditions,
                values,
                options,
            )
            .await;
        }
        DatabaseType::SQLite => {
            return sqlite::genertate_update_data_sql(
                ds_id,
                meta_datasource,
                class_identifier,
                conditions,
                values,
                options,
            )
            .await;
        }
        _ => {}
    }
    Ok((String::new(), vec![]))
}
